package com.htfyun.roobofactory.rooboUtils;

import android.util.Log;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;


public class ZipUtil {
    public static final boolean bDebug = true;
    private static final String TAG = "ZipUtil";

    /**
     * 从 ZIP 文件中解压缩指定的文件
     *
     * @param zipFilename     要解压缩的 ZIP 文件
     * @param extractFilename 要从 ZIP 中解压缩出来的文件
     * @return 成功则返回 true，失败则返回 false.
     */
    public static boolean extract(String zipFilename, String extractFilename, File output) {

        ExtractSingleFileCallback callback = new ExtractSingleFileCallback();
        callback.filename = extractFilename;
        callback.output = output;

        traverseZipFile(zipFilename, callback);
        return callback.succeeded;
    }

    /**
     * 遍历 ZIP 里的每个文件/目录.
     *
     * @param filename 要遍历的ZIP文件
     * @param callback 每遍历一个文件/目录，都会调用此接口
     */
    public static void traverseZipFile(String filename, ZipTraversalCallback callback) {
        ZipFile zipFile = null;
        try {
            zipFile = new ZipFile(filename);
            Enumeration<? extends ZipEntry> emu = zipFile.entries();
            while (emu.hasMoreElements()) {
                ZipEntry entry = emu.nextElement();
                if (callback.onProgress(zipFile, entry)) {
                    break;
                }
            }
        } catch (Exception e) {
            if (bDebug) {
                Log.e(TAG, "", e);
            }
        } finally {
            if (zipFile != null) {
                try {
                    zipFile.close();
                } catch (Exception e) {
                    if (bDebug) {
                        Log.e(TAG, "", e);
                    }
                }
            }
        }
    }

    /**
     * 这是为文件 Copy 准备的方法。
     */
    public static void copyStream(InputStream source, OutputStream target) throws IOException {
        // Copy
        final int BUF_SIZE = 4096;
        byte[] buffer = new byte[BUF_SIZE];
        int length = 0;
        while ((length = source.read(buffer)) > 0) {
            target.write(buffer, 0, length);
        }
        target.flush();
    }

    /**
     * {@link ZipUtil#traverseZipFile(String, ZipTraversalCallback)} 的回调接口。
     *
     * @author zhangxu
     */
    public interface ZipTraversalCallback {
        /**
         * 遍历 ZIP 里每个文件/目录时调用此接口
         *
         * @param entry ZipEntry
         * @return 如果需要中断遍历，返回 true，否则返回 false.
         */
        public boolean onProgress(ZipFile zipFile, ZipEntry entry) throws IOException;
    }

    /**
     * {@link ZipUtil#extract(String, String, File)} 用的回调类
     */
    static class ExtractSingleFileCallback implements ZipTraversalCallback {

        /**
         * 解压缩成功
         */
        boolean succeeded = false;

        // 下面是需要传递的参数
        String filename;
        File output;

        @Override
        public boolean onProgress(ZipFile zipFile, ZipEntry entry) throws IOException {
            if (entry.isDirectory()) {
                return false;
            }

            if (filename.equals(entry.getName())) {
                InputStream is = zipFile.getInputStream(entry);
                OutputStream os = new FileOutputStream(output);
                copyStream(is, os);
                is.close();
                os.close();
                succeeded = true;
                return true;
            } else {
                return false;
            }
        }
    }
}
